//
//  Http+Extension.swift
//  Health-Doctor
//
//  Created by 勇胡 on 2022/7/4.
//  Copyright © 2022 掌上卫健. All rights reserved.
//

import Foundation
import Moya
import Alamofire

extension TargetType {
    
    
    /// 获取http的header
    /// - Parameter isAuthLogin: 是否是授权登录
    func getHttpHeader(_ isLogin:Bool = false,isAutoLogin:Bool = false,token:String)->[String:String] {
        /// 判断有token就传token;
        let currentVersion = Bundle.main.infoDictionary?.strValue("CFBundleShortVersionString") ?? ""
        var httpHeaderParam:[String:String] = [:]
        if isLogin {
            httpHeaderParam = [
                "User-Auth-Agent":"os=2;client=3;ver=\(currentVersion);role=2"
            ]
            
            //自动通过token登录获取当前token
            if isAutoLogin{
                httpHeaderParam["token"] = token
            }
            
        }else{
            httpHeaderParam = [
                "PP-User-Agent": "os=2;ver=\(currentVersion);ctype=2;imei=\(UUID.init().uuidString)",
                "token":token
            ]
        }
        return httpHeaderParam
    }
    
}


//get请求请使用这种方式
struct GetEncoding: ParameterEncoding {
    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var request = try URLEncoding().encode(urlRequest, with: parameters)
        request.url = URL(string: request.url!.absoluteString.replacingOccurrences(of: "%5B%5D=", with: "="))
        return request
    }
}

extension MoyaProvider {
    
    private func findTypeBy(statusCode:Int)->CodeType{
        return CodeType(rawValue: statusCode) ?? .errorOther
    }
    
    /// 网络请求，统一处理（方便后期对每个网络请求拦截、日志记录等操作）
    @discardableResult
    func httpRequst(_ action:TargetType,callbackQueue: DispatchQueue? = .none,onFinish:@escaping ((_ result:ResponseModel)->()))->Cancellable {
        
        return self.request(action as! Target,callbackQueue: callbackQueue) {[weak self](result) in
            guard let `self` = self else { return }
            
            switch result {
            case .success(let response):
                
                //请求失败（非业务失败）
                if response.statusCode != CodeType.success.rawValue{
                    let tempModel = ResponseModel()
                    tempModel.msg = "服务请求失败,请稍后重试!(\(response.statusCode))"
                    tempModel.httpStatus = self.findTypeBy(statusCode: response.statusCode)
                    print("报错了：(\(response.statusCode)  \(action.path)可能是 task: Task的类型设置错误了，一般是json和url两种 或 Get/Post用错了，还有可能是请求头里（User-Auth-Agent 和 PP-User-Agent用错了）、也有可能是服务器在重启")
                    onFinish(tempModel)
                    return
                }
                
                do {
                    let jsonDic:[String:Any] = try response.mapJSON() as? [String:Any] ?? [:]
                    
                    if let tempModel = ResponseModel.deserialize(from: jsonDic){
                        //优先取状态码
                        if tempModel.msg.isEmpty{
                            if tempModel.status > 0,let errorEnum = HttpCode(rawValue:tempModel.status){
                                //错误码99，老系统，错误信息返回在data里面
                                if errorEnum == .OLD_ERROR_99{
                                    tempModel.msg = jsonDic.strValue("data")
                                }else{
                                    tempModel.msg = errorEnum.tipString
                                }
                            }
                        }
                        
                        //兼容第一个字段(有些接口错误信息返这个字段，比如开单接口)
                        let message = jsonDic.strValue("message")
                        if tempModel.msg.isEmpty && !message.isEmpty{
                            tempModel.msg = message
                        } 
                        
                        //兼容第二个字段(兼容，有些接口错误信息返这个字段，比如省云平台第三方接口)
                        let error = jsonDic.strValue("error")
                        if tempModel.msg.isEmpty && !error.isEmpty{
                            tempModel.msg = error
                        }
                        
                        //最后没取到则显示未知错误
                        if tempModel.status > 0 && tempModel.msg.isEmpty{
                            tempModel.msg = "未知错误(\(tempModel.status))"
                        }
                        
                        
                        //这种采用Alert弹框，而不是message
                        if tempModel.status == 100 && !tempModel.msg.isEmpty{
                            MyMessage.showText(message: tempModel.msg)
                            LogUtil.print(info: "网络接口请求内部已弹框，外部就不用弹框了")
                            //清空，外层就不会弹了
                            tempModel.msg = ""
                        }
                        //老系统状错误态码（新系统错误状态码通过status判断，
                        //而老系统接口错误状态码通过extendCode返回的316）
                        //有些网络请求通过findPublicError方法进行拦截进行提醒，但是很多老页面并没有拦截，这里转换一下，
                        //不然通过isSuccess()判断会忽略该错误，导致不会弹框提醒
                        if tempModel.status == 0 && tempModel.extendCode == 316 && !tempModel.msg.isEmpty{
                            tempModel.status = 316
                        }
                        
                        tempModel.httpStatus = self.findTypeBy(statusCode: response.statusCode)
                        tempModel.setDataValue(jsonDic)
                        //请求更新时间
                        if let time = response.response?.allHeaderFields.strValue("reTime"){
                            tempModel.time = time
                        }
                        
                        
                        //兼容云平台授权接口错误信息
                        if tempModel.status > 0 && !tempModel.msg.isEmpty && action.baseURL.relativeString.contain(CloudApiService.shared.getIpAddress()){
                            MyMessage.showText(message: tempModel.msg)
                            
                            //授权接口，登录失效，登录过期
                            if CloudApiService.shared.isLoginExpiry(msg: tempModel.msg){
                                
                                
                                
                                //授权接口，密码错误
                            }else if CloudApiService.shared.isPasswordError(msg: tempModel.msg){
                                
                                
                            }
                        }
                        
                        onFinish(tempModel)
                    }
                    
                } catch{
                    let tempModel = ResponseModel()
                    tempModel.msg = "数据解析错误(格式)"
                    onFinish(tempModel)
                }
                
            case .failure(let error):
               print("\n>>>错误信息 error:\(error)\n")
                
                let tempModel = ResponseModel()
                tempModel.msg = error.localizedDescription
                if tempModel.msg.contains("似乎已断开与互联网的连接。") || tempModel.msg.contains("目前不允许数据连接"){
                    tempModel.msg = "当前网络已断开"
                    tempModel.httpStatus = CodeType.noNetworkConnection
                }
                //请求已取消
                if tempModel.msg.contain("Request explicitly cancelled"){
                    tempModel.msg = ""
                }
                //********超时
                if tempModel.msg.contain("Therequest timed out"){
                    //
                    let time = DateUtil.currentDateTime(format: "yyyy-MM-dd HH:mm:ss")
                    tempModel.msg = "请求超时(\(action.path):\(time))"
                }
                //方便调试
                if tempModel.msg.contain("未能找到使用指定主机名的服务器"){
                    
                    let msg = "当前网络不稳定，域名解析失败。"
                    //清空消息后，外面就不会弹框了
                    tempModel.msg = ""
                    //线上环境域名解析失败,重启app重新解析，根据多次测试，重启后用户可以正常解析
                    MyMessage.showText(message: msg)
                }
                onFinish(tempModel)
                
            }
        }
    }
    
}
